home *** CD-ROM | disk | FTP | other *** search
- Path: apccorp.apcc.com!root
- From: nfegan@apcc.com (Noel Fegan)
- Newsgroups: comp.lang.c++
- Subject: Re: polymorphism and style
- Date: Tue, 27 Feb 1996 09:55:33 GMT
- Organization: American Power Conversion
- Message-ID: <4gukfu$amc@apccorp.apcc.com>
- References: <4gr4ur$n13@alpha.pcix.com>
- NNTP-Posting-Host: hewie.galway.apcc.com
- X-Newsreader: Forte Free Agent 1.0.82
-
- ed lizewski <elizewsk@capecod.net> wrote:
-
- > Question on polymorphism and style.
- >Want to call a function in a most derived class off a pointer to the base
- >class. The fuction does not exist in the base class.
- >I should:
- >1)downcast ?
- >2)add the function to the base class and add virtual stubs to every
- > class that does not use it ?
- >3)add it to the base class but define it like
- > foo( ..whatever..) {error_msg("virtual function not defined");}
- > This way only the class that uses it would have to define it.
- >4) ?
- >
- >thanks for your time.
-
- If you add a virtual stub function in the base class for every virtual function
- in the derived class, or derived classes, then you are adding unnecessary
- complexity to the base class. On top of that, sometimes the source of the base
- classes we interact with are not ours to add to, or it is not wise to mess with
- them, take MFC for example.
-
- In most cases, it is OK to cast the base pointer to the derived type, but you
- must be sure that you are doing a valid cast. The compiler can tell you that a
- cast is invalid only in the case that you are casting a base class pointer to an
- unrelated type. Once the cast is to a valid derived class the compiler accepts
- that you know what you are doing, even though the actual object may have been
- constructed as something else.
-
- There are precautions you can take to safe guard against this type of situation
- arising. If you create an object of a derived type, then you should refer to it
- through its actual class type as much as possible.
-
- For example, say we have a class called Window which forms the base class for a
- windowing class library.
-
- //simplified Window class
- class Window {
- private:
- Window * m_parent;
- public:
- Window (Window * parent) : m_parent(parent) { }
- virtual Window * GetParent (void) { return(m_parent); }
- };
-
- From this class we derive class like ControlWindow, EditControl, ...
-
- //simplified ControlWindow class
- class ControlWindow : public Window {
- public:
- ControlWindow (Window * parent) : Window(parent) { }
- };
-
- class EditControl : public ControlWindow {
- public:
- EditControl (ControlWindow * parent, /*other args*/) : ControlWindow(parent)
- { ...}
- };
-
- When we construct an EditControl object we do it as follows:
-
- EditControl * pEdit = new EditControl(this, /* other args */);
-
- If we then want to pass a pointer to this object to a function which
- specifically requires an EditControl (or some derived class of EditControl), we
- do not make the pointer argument to the function be anything less than
- EditControl. If you make the function argument Window then you are leaving
- youself open to misuse and you cannot be sure that any casting you do in the
- function. The constructor for EditControl takes a pointer to a ControlWindow (a
- type derived form Window) ) as the type of its parent. If the function mentioned
- above calls GetParent() , a base class virtual function which returns a Window
- *, we know that we can safely cast this to ControlWindow because we have kept
- good control over our pointer types.
-
- If you look at the MFC source code you will see quite a lot of casting of this
- type, if its OK for MFC, it's OK for me.
- --
- Noel Fegan
- American Power Conversion
-
-